package com.ajocer.springbootinit.aop;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * 性能监控切面
 * 用于监控方法执行时间并记录指标 */
@Aspect
@Component
@Slf4j
public class PerformanceMonitorAspect {

    @Autowired
    private MeterRegistry meterRegistry;

    /**
     * 定义切点 - 所有控制器方法
     */
    @Pointcut("execution(* com.ajocer.springbootinit.controller.*.*(..))")
    public void controllerPointcut() {}

    /**
     * 定义切点 - 服务层方法
     */
    @Pointcut("execution(* com.ajocer.springbootinit.service.*.*(..))")
    public void servicePointcut() {}

    /**
     * 定义切点 - RAG服务方法
     */
    @Pointcut("execution(* com.ajocer.springbootinit.rag.*.*(..))")
    public void ragServicePointcut() {}

    /**
     * 监控控制器方法执行时间
     */
    @Around("controllerPointcut()")
    public Object monitorControllerPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
        return monitorMethodPerformance(joinPoint, "controller");
    }

    /**
     * 监控服务层方法执行时间
     */
    @Around("servicePointcut()")
    public Object monitorServicePerformance(ProceedingJoinPoint joinPoint) throws Throwable {
        return monitorMethodPerformance(joinPoint, "service");
    }

    /**
     * 监控RAG服务方法执行时间
     */
    @Around("ragServicePointcut()")
    public Object monitorRagServicePerformance(ProceedingJoinPoint joinPoint) throws Throwable {
        return monitorMethodPerformance(joinPoint, "rag");
    }

    /**
     * 监控方法执行时间并记录指标
     */
    private Object monitorMethodPerformance(ProceedingJoinPoint joinPoint, String type) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String methodName = method.getName();
        String className = method.getDeclaringClass().getSimpleName();
        String fullMethodName = className + "." + methodName;

        // 创建计时器
        Timer timer = Timer.builder("method.execution.time")
                .tag("type", type)
                .tag("class", className)
                .tag("method", methodName)
                .description("Method execution time")
                .register(meterRegistry);

        // 记录开始时间
        long startTime = System.nanoTime();

        try {
            // 执行目标方法
            Object result = joinPoint.proceed();

            // 记录执行时间
            long executionTime = System.nanoTime() - startTime;
            timer.record(executionTime, TimeUnit.NANOSECONDS);

            // 记录慢方法
            if (TimeUnit.NANOSECONDS.toMillis(executionTime) > 200) {
                log.warn("慢方法执行 {} 耗时 {} ms", fullMethodName, TimeUnit.NANOSECONDS.toMillis(executionTime));
            }

            return result;
        } catch (Throwable e) {
            // 记录执行时间（即使发生异常）
            long executionTime = System.nanoTime() - startTime;
            timer.record(executionTime, TimeUnit.NANOSECONDS);

            // 记录异常方法
            log.error("方法执行异常: {} 耗时 {} ms", fullMethodName, TimeUnit.NANOSECONDS.toMillis(executionTime), e);
            throw e;
        }
    }
} 